<?php

if (!defined('IN_SYS'))
    exit('Access Denied');

class mredis {

    static $redis;
     //当前权限认证码
    static $auth;
    static $k;
    static $expireTime;
    static $host;
    static $port;
    static $prefix;

    public static function init() {
        if (!isset(self::$redis)) {
            global $redis_config;
            self::$redis = new \Redis();
            
            self::$port = $redis_config['port'] ? $redis_config['port'] : 6379;
            self::$host = $redis_config['host'] ? $redis_config['host'] : "127.0.0.1";
            self::$redis->connect(self::$host, self::$port, $redis_config['timeout']);
            if (!empty($redis_config['auth'])) {
                self::$redis->auth($redis_config['auth']);
                self::$auth = $redis_config['auth'];
            }
            self::$expireTime = time() + $redis_config['timeout'];
            self::$prefix = $redis_config['prefix'] ? $redis_config['prefix'] : "";
        }
        return self::$redis;
    }
    
 

    /*     * *******************事务的相关方法*********************** */

    /**
     * 监控key,就是一个或多个key添加一个乐观锁
     * 在此期间如果key的值如果发生的改变，刚不能为key设定值
     * 可以重新取得Key的值。
     * @param unknown $key
     */
    public static function watch($key) {
        return self::init()->watch(self::$prefix.$key);
    }

    /**
     * 取消当前链接对所有key的watch
     *  EXEC 命令或 DISCARD 命令先被执行了的话，那么就不需要再执行 UNWATCH 了
     */
    public static function unwatch() {
        return self::init()->unwatch();
    }

    /**
     * 开启一个事务
     * 事务的调用有两种模式Redis::MULTI和Redis::PIPELINE，
     * 默认是Redis::MULTI模式，
     * Redis::PIPELINE管道模式速度更快，但没有任何保证原子性有可能造成数据的丢失
     */
    public static function multi($type = \Redis::MULTI) {
        return self::init()->multi($type);
    }

    /**
     * 执行一个事务
     * 收到 EXEC 命令后进入事务执行，事务中任意命令执行失败，其余的命令依然被执行
     */
    public static function exec() {
        return self::init()->exec();
    }

    /**
     * 回滚一个事务
     */
    public static function discard() {
        return self::init()->discard();
    }

    /**
     * 测试当前链接是不是已经失效
     * 没有失效返回+PONG
     * 失效返回false
     */
    public static function ping() {
        return self::init()->ping();
    }

    public static function auth($auth) {
        return self::init()->auth($auth);
    }
    
     /**
     * 执行原生的redis操作
     * @return \Redis
     */
    public static function getRedis() {
        return self::$redis;
    }

    /*     * ***************hash表操作函数****************** */

    /**
     * 得到hash表中一个字段的值
     * @param string $key 缓存key
     * @param string  $field 字段
     * @return string|false
     */
    public static function hGet($key, $field) {
        return self::init()->hGet(self::$prefix.$key, $field);
    }

    /**
     * 为hash表设定一个字段的值
     * @param string $key 缓存key
     * @param string  $field 字段
     * @param string $value 值。
     * @return bool 
     */
    public static function hSet($key, $field, $value) {
        return self::init()->hSet(self::$prefix.$key, $field, $value);
    }

    /**
     * 判断hash表中，指定field是不是存在
     * @param string $key 缓存key
     * @param string  $field 字段
     * @return bool
     */
    public static function hExists($key, $field) {
        return self::init()->hExists(self::$prefix.$key, $field);
    }

    /**
     * 删除hash表中指定字段 ,支持批量删除
     * @param string $key 缓存key
     * @param string  $field 字段
     * @return int
     */
    public static function hdel($key, $field) {
        $fieldArr = explode(',', $field);
        $delNum = 0;

        foreach ($fieldArr as $row) {
            $row = trim($row);
            $delNum += self::init()->hDel(self::$prefix.$key, $row);
        }

        return $delNum;
    }

    /**
     * 返回hash表元素个数
     * @param string $key 缓存key
     * @return int|bool
     */
    public static function hLen($key) {
        return self::init()->hLen(self::$prefix.$key);
    }

    /**
     * 为hash表设定一个字段的值,如果字段存在，返回false
     * @param string $key 缓存key
     * @param string  $field 字段
     * @param string $value 值。
     * @return bool
     */
    public static function hSetNx($key, $field, $value) {
        return self::init()->hSetNx(self::$prefix.$key, $field, $value);
    }

    /**
     * 为hash表多个字段设定值。
     * @param string $key
     * @param array $value
     * @return array|bool
     */
    public static function hMset($key, $value) {
        if (!is_array($value))
            return false;
        return self::init()->hMset(self::$prefix.$key, $value);
    }

    /**
     * 为hash表多个字段设定值。
     * @param string $key
     * @param array|string $value string以','号分隔字段
     * @return array|bool
     */
    public static function hMget($key, $field) {
        if (!is_array($field))
            $field = explode(',', $field);
        return self::init()->hMget(self::$prefix.$key, $field);
    }

    /**
     * 为hash表设这累加，可以负数
     * @param string $key
     * @param int $field
     * @param string $value
     * @return bool
     */
    public static function hIncrBy($key, $field, $value) {
        $value = intval($value);
        return self::init()->hIncrBy(self::$prefix.$key, $field, $value);
    }

    /**
     * 返回所有hash表的所有字段
     * @param string $key
     * @return array|bool
     */
    public static function hKeys($key) {
        return self::init()->hKeys(self::$prefix.$key);
    }

    /**
     * 返回所有hash表的字段值，为一个索引数组
     * @param string $key
     * @return array|bool
     */
    public static function hVals($key) {
        return self::init()->hVals(self::$prefix.$key);
    }

    /**
     * 返回所有hash表的字段值，为一个关联数组
     * @param string $key
     * @return array|bool
     */
    public static function hGetAll($key) {
        return self::init()->hGetAll(self::$prefix.$key);
    }

    /*     * *******************有序集合操作******************** */

    /**
     * 给当前集合添加一个元素
     * 如果value已经存在，会更新order的值。
     * @param string $key
     * @param string $order 序号
     * @param string $value 值
     * @return bool
     */
    public static function zAdd($key, $order, $value) {
        return self::init()->zAdd(self::$prefix.$key, $order, $value);
    }

    /**
     * 给$value成员的order值，增加$num,可以为负数
     * @param string $key
     * @param string $num 序号
     * @param string $value 值
     * @return 返回新的order
     */
    public static function zinCry($key, $num, $value) {
        return self::init()->zinCrby(self::$prefix.$key, $num, $value);
    }

    /**
     * 删除值为value的元素
     * @param string $key
     * @param stirng $value
     * @return bool
     */
    public static function zRem($key, $value) {
        return self::init()->zRem(self::$prefix.$key, $value);
    }

    /**
     * 集合以order递增排列后，0表示第一个元素，-1表示最后一个元素
     * @param string $key
     * @param int $start
     * @param int $end
     * @return array|bool
     */
    public static function zRange($key, $start, $end) {
        return self::init()->zRange(self::$prefix.$key, $start, $end);
    }

    /**
     * 集合以order递减排列后，0表示第一个元素，-1表示最后一个元素
     * @param string $key
     * @param int $start
     * @param int $end
     * @return array|bool
     */
    public static function zRevRange($key, $start, $end) {
        return self::init()->zRevRange(self::$prefix.$key, $start, $end);
    }

    /**
     * 集合以order递增排列后，返回指定order之间的元素。
     * min和max可以是-inf和+inf　表示最大值，最小值
     * @param string $key
     * @param int $start
     * @param int $end
     * @package array $option 参数
     *     withscores=>true，表示数组下标为Order值，默认返回索引数组
     *     limit=>array(0,1) 表示从0开始，取一条记录。
     * @return array|bool
     */
    public static function zRangeByScore($key, $start = '-inf', $end = "+inf", $option = array()) {
        return self::init()->zRangeByScore(self::$prefix.$key, $start, $end, $option);
    }

    /**
     * 集合以order递减排列后，返回指定order之间的元素。
     * min和max可以是-inf和+inf　表示最大值，最小值
     * @param string $key
     * @param int $start
     * @param int $end
     * @package array $option 参数
     *     withscores=>true，表示数组下标为Order值，默认返回索引数组
     *     limit=>array(0,1) 表示从0开始，取一条记录。
     * @return array|bool
     */
    public static function zRevRangeByScore($key, $start = '-inf', $end = "+inf", $option = array()) {
        return self::init()->zRevRangeByScore(self::$prefix.$key, $start, $end, $option);
    }

    /**
     * 返回order值在start end之间的数量
     * @param unknown $key
     * @param unknown $start
     * @param unknown $end
     */
    public static function zCount($key, $start, $end) {
        return self::init()->zCount(self::$prefix.$key, $start, $end);
    }

    /**
     * 返回值为value的order值
     * @param unknown $key
     * @param unknown $value
     */
    public static function zScore($key, $value) {
        return self::init()->zScore(self::$prefix.$key, $value);
    }

    /**
     * 返回集合以score递增加排序后，指定成员的排序号，从0开始。
     * @param unknown $key
     * @param unknown $value
     */
    public static function zRank($key, $value) {
        return self::init()->zRank(self::$prefix.$key, $value);
    }

    /**
     * 返回集合以score递增加排序后，指定成员的排序号，从0开始。
     * @param unknown $key
     * @param unknown $value
     */
    public static function zRevRank($key, $value) {
        return self::init()->zRevRank(self::$prefix.$key, $value);
    }

    /**
     * 删除集合中，score值在start end之间的元素　包括start end
     * min和max可以是-inf和+inf　表示最大值，最小值
     * @param unknown $key
     * @param unknown $start
     * @param unknown $end
     * @return 删除成员的数量。
     */
    public static function zRemRangeByScore($key, $start, $end) {
        return self::init()->zRemRangeByScore(self::$prefix.$key, $start, $end);
    }

    /**
     * 返回集合元素个数。
     * @param unknown $key
     */
    public static function zCard($key) {
        return self::init()->zCard(self::$prefix.$key);
    }

    /*     * *******************队列操作命令*********************** */

    /**
     * 在队列尾部插入一个元素
     * @param unknown $key
     * @param unknown $value
     * 返回队列长度
     */
    public static function rPush($key, $value) {
        return self::init()->rPush(self::$prefix.$key, $value);
    }

    /**
     * 在队列尾部插入一个元素 如果key不存在，什么也不做
     * @param unknown $key
     * @param unknown $value
     * 返回队列长度
     */
    public static function rPushx($key, $value) {
        return self::init()->rPushx(self::$prefix.$key, $value);
    }

    /**
     * 在队列头部插入一个元素
     * @param unknown $key
     * @param unknown $value
     * 返回队列长度
     */
    public static function lPush($key, $value) {
        return self::init()->lPush(self::$prefix.$key, $value);
    }

    /**
     * 在队列头插入一个元素 如果key不存在，什么也不做
     * @param unknown $key
     * @param unknown $value
     * 返回队列长度
     */
    public static function lPushx($key, $value) {
        return self::init()->lPushx(self::$prefix.$key, $value);
    }

    /**
     * 返回队列长度
     * @param unknown $key
     */
    public static function lLen($key) {
        return self::init()->lLen(self::$prefix.$key);
    }

    /**
     * 返回队列指定区间的元素
     * @param unknown $key
     * @param unknown $start
     * @param unknown $end
     */
    public static function lRange($key, $start, $end) {
        return self::init()->lrange(self::$prefix.$key, $start, $end);
    }

    /**
     * 返回队列中指定索引的元素
     * @param unknown $key
     * @param unknown $index
     */
    public static function lIndex($key, $index) {
        return self::init()->lIndex(self::$prefix.$key, $index);
    }

    /**
     * 设定队列中指定index的值。
     * @param unknown $key
     * @param unknown $index
     * @param unknown $value
     */
    public static function lSet($key, $index, $value) {
        return self::init()->lSet(self::$prefix.$key, $index, $value);
    }

    /**
     * 删除值为vaule的count个元素
     * PHP-REDIS扩展的数据顺序与命令的顺序不太一样，不知道是不是bug
     * count>0 从尾部开始
     *  >0　从头部开始
     *  =0　删除全部
     * @param unknown $key
     * @param unknown $count
     * @param unknown $value
     */
    public static function lRem($key, $count, $value) {
        return self::init()->lRem(self::$prefix.$key, $value, $count);
    }

    /**
     * 删除并返回队列中的头元素。
     * @param unknown $key
     */
    public static function lPop($key) {
        return self::init()->lPop(self::$prefix.$key);
    }

    /**
     * 删除并返回队列中的尾元素
     * @param unknown $key
     */
    public static function rPop($key) {
        
        return self::init()->rPop(self::$prefix.$key);
    }

    /*     * ***********redis字符串操作命令**************** */

    /**
     * 设置一个key
     * @param unknown $key
     * @param unknown $value
     */
    public static function set($key, $value) {
        return self::init()->set(self::$prefix.$key, $value);
    }

    /**
     * 得到一个key
     * @param unknown $key
     */
    public static function get($key) {
        return self::init()->get(self::$prefix.$key);
    }

    /**
     * 设置一个有过期时间的key
     * @param unknown $key
     * @param unknown $expire
     * @param unknown $value
     */
    public static function setex($key, $expire, $value) {
        return self::init()->setex(self::$prefix.$key, $expire, $value);
    }

    /**
     * 设置一个key,如果key存在,不做任何操作.
     * @param unknown $key
     * @param unknown $value
     */
    public static function setnx($key, $value) {
        return self::init()->setnx(self::$prefix.$key, $value);
    }
    
      /**
     * 设置一个带超时失效的key,如果key存在,不做任何操作.
     * @param unknown $key
     * @param unknown $value
       @param unknown $exprie
     */
    public static function setnxe($key,$value,$exprie=15) {
        return self::init()->set(self::$prefix.$key, $value,array('nx', 'ex' => $exprie));
    }
    
     /**
     * 删除一个key
     * @param unknown $key
     */
    public static function del($key) {
        return self::init()->del(self::$prefix.$key);
    }
    
    /**
     * 删除一个key
     * @param unknown $key
     */
    public static function keys($search_key) {
        return self::init()->keys(self::$prefix.$search_key);
    }
    
    
   
}
